#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
同义词生成器 - 使用NLTK WordNet或其他词库
"""

import random
import json
import os
import logging
from typing import List, Set, Optional

# 获取日志记录器
logger = logging.getLogger(__name__)

try:
    import nltk
    from nltk.corpus import wordnet
    from nltk.corpus import words
    NLTK_AVAILABLE = True
except ImportError:
    NLTK_AVAILABLE = False

try:
    import english_words
    from english_words import english_words_lower_alpha_set
    ENGLISH_WORDS_AVAILABLE = True
except ImportError:
    ENGLISH_WORDS_AVAILABLE = False

class SynonymGenerator:
    """智能同义词生成器"""
    
    def __init__(self):
        self.used_words = set()
        self.word_cache = []
        
        # 尝试初始化不同的词库
        self._init_word_sources()
        
    def _init_word_sources(self):
        """初始化词汇来源"""
        self.sources = []
        
        # 1. 尝试使用 NLTK WordNet
        if NLTK_AVAILABLE:
            try:
                # 尝试使用已有的NLTK数据，不自动下载
                try:
                    nltk.data.find('corpora/wordnet')
                except LookupError:
                    logger.debug("NLTK WordNet数据未安装，跳过")
                    pass

                try:
                    nltk.data.find('corpora/words')
                except LookupError:
                    logger.debug("NLTK words数据未安装，使用english-words替代")
                    if not ENGLISH_WORDS_AVAILABLE:
                        return
                
                # 获取英文单词列表
                from nltk.corpus import words
                word_list = words.words()
                # 过滤：只保留4-12个字符的单词，且全部小写字母
                valid_words = [
                    w.lower() for w in word_list 
                    if 4 <= len(w) <= 12 and w.isalpha()
                ]
                self.word_cache.extend(valid_words[:10000])  # 限制数量避免内存过大
                logger.info(f"已加载 NLTK 词库: {len(valid_words)} 个单词")

            except (ImportError, LookupError, AttributeError) as e:
                logger.warning(f"NLTK 初始化失败: {e}")
        
        # 2. 尝试使用 english-words 包
        if ENGLISH_WORDS_AVAILABLE:
            try:
                # 过滤合适长度的单词
                valid_words = [
                    w for w in english_words_lower_alpha_set
                    if 4 <= len(w) <= 12
                ]
                self.word_cache.extend(list(valid_words)[:10000])
                logger.info(f"已加载 english-words 包: {len(valid_words)} 个单词")
            except (ImportError, AttributeError, TypeError) as e:
                logger.warning(f"english-words 初始化失败: {e}")
        
        # 3. 使用内置的编程相关词汇（fallback）
        self.programming_words = self._load_programming_words()
        
        # 4. 加载本地同义词文件
        self.local_synonyms = self._load_local_synonyms()
        
        # 去重并打乱
        self.word_cache = list(set(self.word_cache))
        random.shuffle(self.word_cache)

        logger.info(f"总计可用词汇: {len(self.word_cache)} 个")
        
    def _load_programming_words(self) -> List[str]:
        """加载编程相关的词汇"""
        return [
            # 动作词
            "execute", "perform", "process", "handle", "manage", "control",
            "fetch", "retrieve", "store", "cache", "buffer", "queue",
            "parse", "analyze", "validate", "verify", "check", "ensure",
            "create", "build", "generate", "produce", "construct", "initialize",
            "update", "modify", "alter", "transform", "convert", "translate",
            
            # 对象词
            "manager", "controller", "handler", "processor", "builder", "factory",
            "service", "provider", "helper", "utility", "adapter", "wrapper",
            "delegate", "observer", "listener", "monitor", "tracker", "watcher",
            "container", "holder", "storage", "repository", "registry", "catalog",
            
            # 技术词
            "alpha", "beta", "gamma", "delta", "epsilon", "sigma", "omega",
            "quantum", "nexus", "matrix", "vector", "tensor", "kernel", "shader",
            "cipher", "crypto", "hasher", "encoder", "decoder", "serializer"
        ]
    
    def _load_local_synonyms(self) -> dict:
        """加载本地同义词文件"""
        synonyms_file = os.path.join(
            os.path.dirname(__file__), 
            '..', 'resources', 'synonyms.json'
        )
        
        if os.path.exists(synonyms_file):
            try:
                with open(synonyms_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    # 提取所有词汇
                    all_words = []
                    for category in data.get('categories', {}).values():
                        all_words.extend(category.get('words', []))
                    return all_words
            except (json.JSONDecodeError, IOError, KeyError) as e:
                logger.warning(f"加载本地同义词失败: {e}")
        
        return []
    
    def get_synonym(self, original_word: str, word_type: str = None) -> str:
        """
        获取一个同义词或替代词
        
        Args:
            original_word: 原始单词
            word_type: 词的类型 (class/method/property/variable)
        
        Returns:
            替代词
        """
        # 如果启用了WordNet，尝试查找真正的同义词
        if NLTK_AVAILABLE and random.random() < 0.3:  # 30%概率使用真同义词
            synonyms = self._get_wordnet_synonyms(original_word)
            if synonyms:
                # 过滤掉已使用的词
                available = [s for s in synonyms if s not in self.used_words]
                if available:
                    chosen = random.choice(available)
                    self.used_words.add(chosen)
                    return chosen
        
        # 根据词类型选择合适的替代词
        if word_type == 'class':
            return self._get_class_name()
        elif word_type == 'method':
            return self._get_method_name()
        elif word_type == 'property':
            return self._get_property_name()
        else:
            return self._get_random_word()
    
    def _get_wordnet_synonyms(self, word: str) -> List[str]:
        """
        使用WordNet获取同义词
        :param word: 原始单词
        :return: 同义词列表
        """
        if not NLTK_AVAILABLE:
            return []
        
        synonyms = []
        try:
            for syn in wordnet.synsets(word):
                for lemma in syn.lemmas():
                    synonym = lemma.name().replace('_', '')
                    if synonym != word and synonym.isalpha() and 4 <= len(synonym) <= 12:
                        synonyms.append(synonym.lower())
        except:
            pass
        
        return list(set(synonyms))
    
    def _get_class_name(self) -> str:
        """
        生成类名风格的词
        """
        # 类名通常是名词，首字母大写
        prefixes = ["Base", "Core", "Main", "Default", "Custom", "Abstract", ""]
        suffixes = ["Manager", "Controller", "Service", "Handler", "Provider", "Factory", ""]
        
        base = self._get_random_word()
        prefix = random.choice(prefixes)
        suffix = random.choice(suffixes)
        
        # 首字母大写
        base = base.capitalize()
        
        return f"{prefix}{base}{suffix}"
    
    def _get_method_name(self) -> str:
        """
        生成方法名风格的词
        """
        # 方法名通常是动词开头，驼峰命名
        verbs = ["get", "set", "update", "create", "delete", "process", "handle", "execute", ""]
        
        verb = random.choice(verbs)
        noun = self._get_random_word()
        
        if verb:
            # 驼峰命名
            return f"{verb}{noun.capitalize()}"
        else:
            return noun
    
    def _get_property_name(self) -> str:
        """
        生成属性名风格的词
        """
        # 属性名通常是名词，可能有前缀
        prefixes = ["is", "has", "can", "should", "current", "selected", ""]
        
        prefix = random.choice(prefixes)
        base = self._get_random_word()
        
        if prefix and prefix in ["is", "has", "can", "should"]:
            # 布尔类型属性
            return f"{prefix}{base.capitalize()}"
        elif prefix:
            return f"{prefix}{base.capitalize()}"
        else:
            return base
    
    def _get_random_word(self) -> str:
        """
        获取一个随机单词
        """
        # 优先从大词库中选择
        if self.word_cache:
            available = [w for w in self.word_cache if w not in self.used_words]
            if available:
                word = random.choice(available)
                self.used_words.add(word)
                return word
        
        # 如果词库用尽，使用编程词汇
        if self.programming_words:
            available = [w for w in self.programming_words if w not in self.used_words]
            if available:
                word = random.choice(available)
                self.used_words.add(word)
                return word
        
        # 最后的fallback：生成随机组合
        prefixes = ["neo", "meta", "proto", "pseudo", "quasi", "ultra", "hyper", "super"]
        bases = ["morph", "form", "type", "kind", "mode", "state", "phase", "stage"]
        numbers = ["", "2", "3", "X", "Plus", "Pro", "Max", "Ultra"]
        
        word = f"{random.choice(prefixes)}{random.choice(bases)}{random.choice(numbers)}"
        self.used_words.add(word)
        return word
    
    def reset(self):
        """重置已使用的词汇"""
        self.used_words.clear()
        random.shuffle(self.word_cache)


# 使用示例
if __name__ == "__main__":
    # 配置日志用于测试
    logging.basicConfig(level=logging.INFO, format='%(message)s')

    generator = SynonymGenerator()

    # 测试不同类型的名称生成
    logger.info("\n测试类名生成:")
    for _ in range(5):
        logger.info(f"  {generator.get_synonym('UserModel', 'class')}")

    logger.info("\n测试方法名生成:")
    for _ in range(5):
        logger.info(f"  {generator.get_synonym('loadData', 'method')}")

    logger.info("\n测试属性名生成:")
    for _ in range(5):
        logger.info(f"  {generator.get_synonym('userName', 'property')}")

    logger.info("\n测试随机词生成:")
    for _ in range(5):
        logger.info(f"  {generator.get_synonym('something', None)}")